/* NOCOMMAN.C */

#include <notes.g>
#include <notes.rsg>
#include <hwim.h>
#include <scrimg.g>
#include <s_.rsg>
#include "nolayout.h"
#include "notes.def"

GLREF_D PR_HWIMMAN *w_am;
GLREF_D PR_WSERV *w_ws;
GLREF_D WSERV_SPEC *wserv_channel;
GLREF_D PR_VAFLAT *DatApp1;
GLREF_D PR_NOCOMMAN *DatApp2;
GLREF_D PR_EDWIN *DatApp3;
GLREF_D NOTE *DatApp4;

GLDEF_D LAYOUT_DATA ld;

LOCAL_C VOID RotateStatusWindow(VOID)
    {
    P_EXTENT ext;

    if (ld.Version4)
        {
        if (!ld.StatusWindow--)
            ld.StatusWindow=W_STATUS_WINDOW_BIG;
        wStatusWindow(ld.StatusWindow);
        wInquireStatusWindow(-1,&ext);
        ld.StatusWindowWidth=ext.width;
        }
    else
        {
        if (ld.StatusWindow^=TRUE)
            {
            wsEnable();
            ld.StatusWindowWidth=WS_WIDTH;
            }
        else
            {
            wsDisable();
            ld.StatusWindowWidth=0;
            }
        }
    }

LOCAL_C VOID InitStatusWindow(VOID)
    {
    if (ld.Version4)
        wsSetList(W_STATUS_WINDOW_ICON,NULL,0);
    RotateStatusWindow();
    }

LOCAL_C VOID GetFontHeightData(VOID)
    {
    G_FONT_INFO font;

    gFontInfo(WS_FONT_SYSTEM,0,&font);
    ld.FontHeight=font.height;
    ld.FontAscent=font.ascent;
    }

LOCAL_C VOID CreateTextWindows(PR_NOCOMMAN *self)
    {
    self->nocomman.tagwin=f_new(CAT_NOTES_NOTES,C_NOTAGWIN);
    self->nocomman.cntwin=f_new(CAT_NOTES_NOTES,C_NOCNTWIN);
    }

LOCAL_C VOID InitTextWindow(VOID *win,INT x,INT y,INT width)
    {
    W_WINDATA wd;

    wd.background=W_WIN_BACK_NONE;
    wd.extent.tl.x=x;
    wd.extent.tl.y=y+EDGE_TLY;
    wd.extent.width=width;
    wd.extent.height=ld.FontHeight+2;
    p_send5(win,O_WN_CONNECT,NULL,W_WIN_BACKGROUND|W_WIN_EXTENT,&wd);
    hInitVis(win);
    }

LOCAL_C VOID MoveWindowLeft(INT wid,INT change)
    {
    W_WINDATA wd;

    wInquireWindow(wid,&wd);
    wd.extent.tl.x+=change;
    wSetWindow(wid,W_WIN_EXTENT,&wd);
    }

LOCAL_C UINT CalculateYValues(UWORD *py1,UWORD *py2)
    {
    UWORD NumLines;
    UWORD LineHeight;
    UWORD spare;

    LineHeight=ld.FontHeight+2;
    NumLines=(ld.ScreenHeight-REQD_EDGE_PIXELS)/LineHeight;
    spare=ld.ScreenHeight-REQD_EDGE_PIXELS-LineHeight*NumLines;
    spare>>=1;      /* excess goes to second "spare" region */
    *py1=EDGE_HEIGHT+LineHeight+BASIC_GAP_BETWEEN_WINDOWS+spare;
    *py2=ld.ScreenHeight-(EDGE_HEIGHT+LineHeight);
    return(NumLines-2);
    }

LOCAL_C VOID SetupInEdwin(IN_EDWIN *pInit,INT delx,INT flags,INT maxlen)
    {
    pInit->vulen=ld.ScreenWidth-ld.StatusWindowWidth-delx;
    pInit->flags=flags;
    pInit->maxlen=maxlen;
    pInit->contents[0]=0;
    }

LOCAL_C PR_NOWIN *CreateNowin(INT class,IN_EDWIN *pIned,IN_EDWIN_X *pIX)
    {
    PR_NOWIN *nowin;

    nowin=f_newsend(CAT_NOTES_NOTES,class,O_WN_INIT,pIned,pIX);
    hInitVis(nowin);
    return(nowin);
    }

#define EDWIN_FLGS (IN_EDWIN_VULEN_PIXELS|IN_EDWIN_POSITION_SUPPLIED)

LOCAL_C VOID InitialiseWindows(PR_NOCOMMAN *self)
    {
    UWORD x1,x2;
    UWORD y1,y2;
    UWORD NumNotesLines;
    IN_EDWIN ined;
    IN_EDWIN_X inedx;

    CreateTextWindows(self);
    x1=p_send2(self->nocomman.tagwin,O_WN_SENSE);
    x2=p_send2(self->nocomman.cntwin,O_WN_SENSE);
    NumNotesLines=CalculateYValues(&y1,&y2);
    SetupInEdwin(&ined,x1,EDWIN_FLGS|IN_EDWIN_FONT_SUPPLIED,40);
    inedx.pos.x=x1;
    inedx.pos.y=0;
    if (ld.Version4)
        {
        inedx.font=WS_FONT_SYSTEM;
        inedx.style=G_STY_BOLD;
        }
    else
        {
        inedx.font=WS_FONT_BASE+1;
        inedx.style=G_STY_NORMAL;
        }
    self->nocomman.edit[0]=CreateNowin(C_NOTITWIN,&ined,&inedx);
    SetupInEdwin(&ined,0,EDWIN_FLGS|IN_EDWIN_VISLINES_SUPPLIED|
                            IN_EDWIN_LEFT_CURSOR|IN_EDWIN_CLIPBOARD,512);
    inedx.pos.x=0;
    inedx.pos.y=y1;
    inedx.vislines=NumNotesLines;
    inedx.clip=NULL;
    self->nocomman.edit[1]=CreateNowin(C_NOWIN,&ined,&inedx);
    SetupInEdwin(&ined,x2,EDWIN_FLGS,20);
    inedx.pos.x=0;
    inedx.pos.y=y2;
    self->nocomman.edit[2]=CreateNowin(C_NOFNDWIN,&ined,&inedx);
    InitTextWindow(self->nocomman.tagwin,0,0,x1);
    InitTextWindow(self->nocomman.cntwin,
                            ld.ScreenWidth-ld.StatusWindowWidth-x2,y2,x2);
    }

LOCAL_C VOID InitialiseLayout(PR_NOCOMMAN *self)
    {
    ld.Version4=
      ((wserv_channel->conn.info.version_id&WS_VERSION_MASK) >= WS_VERSION_4);
    InitStatusWindow();
    ld.ScreenWidth=wserv_channel->conn.info.pixels.x;
    ld.ScreenHeight=wserv_channel->conn.info.pixels.y;
    GetFontHeightData();
    InitialiseWindows(self);
    DatApp3=self->nocomman.edit[NOTES_WINDOW]->nowin.edwin;
    }

LOCAL_C VOID FocusTo(PR_NOCOMMAN *self,INT which)
    {
    if (w_ws->wserv.cli)
        p_send3(w_ws->wserv.cli,O_WN_EMPHASISE,FALSE);
    self->nocomman.which=which;
    w_ws->wserv.cli=(PR_WIN *)self->nocomman.edit[which];
    p_send3(w_ws->wserv.cli,O_WN_EMPHASISE,TRUE);
    }

LOCAL_C VOID FocusToWithCheck(PR_NOCOMMAN *self,INT which)
    {
    if (which==self->nocomman.which)
        return;
    FocusTo(self,which);
    }

LOCAL_C VOID RecordChange(PR_NOWIN *win,LENBUF *lb)
    {
    PR_EDWIN *edwin;
    SE_EDWIN sense;

    edwin=win->nowin.edwin;
    if (!(edwin->edwin.change))
        return;
    p_send3(edwin,O_WN_SENSE,&sense);
    lb->buf=f_realloc(lb->buf,sense.len);
    lb->len=sense.len;
    p_bcpy(lb->buf,sense.buf,sense.len);
    edwin->edwin.change=FALSE;
    }

LOCAL_C VOID RecordAnyChanges(PR_NOCOMMAN *self)
    {
    RecordChange(self->nocomman.edit[TITLE_WINDOW],&DatApp4->title);
    RecordChange(self->nocomman.edit[NOTES_WINDOW],&DatApp4->note);
    }

LOCAL_C VOID SetCurrentNote(PR_NOCOMMAN *self)
    {
    DatApp4=ePointToNote(self->nocomman.where);
    }

LOCAL_C VOID LoadEditor(PR_NOWIN *win,LENBUF *lb)
    {
    PR_EDWIN *edwin;
    SE_EDWIN set;

    edwin=win->nowin.edwin;
    set.buf=lb->buf;
    set.len=lb->len;
    p_send3(edwin,O_WN_SET,&set);
    edwin->edwin.change=FALSE;
    }

LOCAL_C VOID LoadTagStatus(PR_NOCOMMAN *self)
    {
    p_send3(self->nocomman.tagwin,O_WN_SET,DatApp4->tagged);
    }

LOCAL_C VOID LoadWhereAndCount(PR_NOCOMMAN *self)
    {
    p_send4(self->nocomman.cntwin,
                    O_WN_SET,self->nocomman.where+1,DatApp1->varoot.nrec);
    }

LOCAL_C VOID LoadWindows(PR_NOCOMMAN *self)
    {
    LoadEditor(self->nocomman.edit[TITLE_WINDOW],&DatApp4->title);
    LoadEditor(self->nocomman.edit[NOTES_WINDOW],&DatApp4->note);
    LoadWhereAndCount(self);
    LoadTagStatus(self);
    }

LOCAL_C VOID CheckEditing(PR_NOCOMMAN *self)
    {
    if (self->nocomman.which==NOTES_WINDOW)
        return;
    hInfoPrint(NOSTR_ONLY_IN_NOTES);
    p_leave(RUN_ACTIVE_USED);
    }

LOCAL_C VOID GiveTagCount(VOID)
    {
    hInfoPrint(NOSTR_TAG_COUNT,eCountTaggedNotes());
    }

LOCAL_C INT RunDialog(INT class,INT resid,VOID *rbuf)
    {
    DL_DATA dd;

    dd.id=resid;
    dd.rbuf=rbuf;
    dd.pdlg=NULL;
    return(hLaunchDial(CAT_NOTES_NOTES,class,&dd));
    }

LOCAL_C VOID TagCurrentNote(INT clear)
    {
    DatApp4->tagged=(!clear);
    }

LOCAL_C VOID SetTo(PR_NOCOMMAN *self,INT where)
    {
    self->nocomman.where=where;
    SetCurrentNote(self);
    LoadWindows(self);
    }

LOCAL_C VOID WinEmphasise(PR_NOCOMMAN *self,INT which,INT state)
    {
    p_send3(self->nocomman.edit[which]->nowin.edwin,O_WN_EMPHASISE,state);
    }

LOCAL_C VOID SetCursorWidth(PR_NOCOMMAN *self,INT which,INT width)
    {
    PR_EDWIN *edwin;
    SCRIMG_WIN win;

    edwin=self->nocomman.edit[which]->nowin.edwin;
    p_send3(edwin->edwin.scrimg,O_SI_SENSE,&win);
    win.cwidth=width;
    p_send4(edwin->edwin.scrimg,O_SI_SET,&win,NULL);
    }

LOCAL_C VOID SetEdwinSelect(PR_NOCOMMAN *self,INT which,INT aoff,INT coff)
    {
    SET_EDWIN set;

    set.flags=SET_EDWIN_CURSOR|SET_EDWIN_ANCHOR;
    set.anchor=aoff;
    set.cursor=coff;
    p_send3(self->nocomman.edit[which]->nowin.edwin,O_EW_SET,&set);
    }

LOCAL_C VOID DrawImmediately(PR_WIN *win)
    {
    p_send2(win,O_WN_DODRAW);
    }

LOCAL_C VOID Search(PR_NOCOMMAN *self,LENBUF *lb,INT here,INT which)
    {
    INT ind;
    
    if (self->nocomman.casesens)
        ind=p_bsub(lb->buf,lb->len,
                    self->nocomman.pattern.buf,self->nocomman.pattern.len);
    else
        ind=p_bsubi(lb->buf,lb->len,
                    self->nocomman.pattern.buf,self->nocomman.pattern.len);
    if (ind<0)
        return;
    if (here!=self->nocomman.where)
        SetTo(self,here);
    if (self->nocomman.pattern.len)
        {
        if (which!=self->nocomman.which)
            {
            WinEmphasise(self,self->nocomman.which,FALSE);
            SetCursorWidth(self,which,0);
            WinEmphasise(self,which,TRUE);
            }
        SetEdwinSelect(self,which,ind,ind+self->nocomman.pattern.len);
        if (which!=self->nocomman.which)
            {
            DrawImmediately((PR_WIN *)self->nocomman.cntwin);
            DrawImmediately((PR_WIN *)self->nocomman.tagwin);
            wFlush();
            p_sleep(5L);
            WinEmphasise(self,which,FALSE);
            SetCursorWidth(self,which,2);
            WinEmphasise(self,self->nocomman.which,TRUE);
            }
        }
    p_leave(RUN_ACTIVE_USED);
    }

LOCAL_C VOID DoSearch(PR_NOCOMMAN *self,INT here,INT direction)
    {
    PR_EDWIN *edwin;
    INT k;
    INT count;
    NOTE *pn;

    RecordAnyChanges(self);
    edwin=self->nocomman.edit[FIND_WINDOW]->nowin.edwin;
    p_send3(edwin,O_WN_SENSE,&self->nocomman.pattern);
    edwin->edwin.change=FALSE;
    k=DatApp1->varoot.nrec;
    count=k-1;
    while (k--)
        {
        here+=direction;
        if (here<0)
            here=count;
        else if (here>count)
            here=0;
        pn=ePointToNote(here);
        if (self->nocomman.findtype!=FIND_NOTES_ONLY)
            Search(self,&pn->title,here,TITLE_WINDOW);
        if (self->nocomman.findtype!=FIND_TITLE_ONLY)
            Search(self,&pn->note,here,NOTES_WINDOW);
        }
    hInfoPrint(NOSTR_NOT_FOUND);
    }

LOCAL_C INT EdwinChanged(PR_NOCOMMAN *self,INT which)
    {
    return(self->nocomman.edit[which]->nowin.edwin->edwin.change);
    }

LOCAL_C VOID CheckIfChanged(PR_NOCOMMAN *self)
    {
    if (EdwinChanged(self,TITLE_WINDOW))
        return;
    if (EdwinChanged(self,NOTES_WINDOW))
        return;
    hInfoPrint(NOSTR_NOT_CHANGED);
    p_leave(RUN_ACTIVE_USED);
    }

LOCAL_C WORD GetLinkableData(ULONG *pFmt)
    {
    return(p_send3(w_am->appman.system,O_SY_LINK_PASTE,pFmt));
    }

#pragma METHOD_CALL

METHOD VOID nocomman_com_init(PR_NOCOMMAN *self)
    {
    DatApp2=self;
    eInitialiseEngine();
    SetCurrentNote(self);
    InitialiseLayout(self);
    LoadWhereAndCount(self);
    FocusTo(self,TITLE_WINDOW);
    InitLinkServer();
    }

METHOD VOID nocomman_com_statwin(PR_NOCOMMAN *self)
    {
    INT change;
    INT i;

    change=ld.StatusWindowWidth;
    RotateStatusWindow();
    change-=ld.StatusWindowWidth;
    for (i=0; i<3; i++)
        p_send3(self->nocomman.edit[i],O_NW_INCREASE_WIDTH,change);
    MoveWindowLeft(self->nocomman.cntwin->win.id,change);
    }

METHOD VOID nocomman_com_exit(VOID)
    {
    p_exit(0);
    }

METHOD VOID nocomman_ncon_new(PR_NOCOMMAN *self)
    {
    RecordAnyChanges(self);
    self->nocomman.where=eAppendNullEntry();
    SetCurrentNote(self);
    LoadWindows(self);
    FocusToWithCheck(self,TITLE_WINDOW);
    }

METHOD VOID nocomman_ncon_insert(PR_NOCOMMAN *self)
    {
    RecordAnyChanges(self);
    if (!self->nocomman.clip.title.len && !self->nocomman.clip.note.len)
        {
        hInfoPrint(NOSTR_NO_NOTE_INSERTED);
        return;
        }
    self->nocomman.where=eAppendNullEntry();
    SetCurrentNote(self);
    eTakeCopy(DatApp4,&self->nocomman.clip);
    LoadWindows(self);
    }

METHOD VOID nocomman_ncon_copy(PR_NOCOMMAN *self)
    {
    NOTE new;

    RecordAnyChanges(self);
    if (!DatApp4->title.len && !DatApp4->note.len)
        {
        hInfoPrint(NOSTR_NO_NOTE_COPIED);
        return;
        }
    eTakeCopy(&new,DatApp4);
    eZeroNote(&self->nocomman.clip);
    self->nocomman.clip=new;
    hInfoPrint(NOSTR_NOTE_COPIED);
    }

METHOD VOID nocomman_ncon_delete(PR_NOCOMMAN *self)
    {
    if (!hConfirm(NOSTR_DELETE_NOTE))
        return;
    self->nocomman.where=eDeleteNote(self->nocomman.where);
    SetCurrentNote(self);
    LoadWindows(self);
    }

METHOD VOID nocomman_ncon_record(PR_NOCOMMAN *self)
    {
    CheckIfChanged(self);
    RecordAnyChanges(self);
    hInfoPrint(NOSTR_NOTE_RECORDED);
    }

METHOD VOID nocomman_ncon_undo(PR_NOCOMMAN *self)
    {
    CheckIfChanged(self);
    if (hConfirm(NOSTR_UNDO_EDITING))
        LoadWindows(self);
    }

METHOD VOID nocomman_ncoe_insert(PR_NOCOMMAN *self)
    {
    CheckEditing(self);
    if (!(p_send2(DatApp3,O_EW_PASTE_CLIP)))
        hInfoPrint(NOSTR_NO_TEXT_INSERTED);
    }

METHOD VOID nocomman_ncoe_copy(PR_NOCOMMAN *self)
    {
    CheckEditing(self);
    if (!(p_send2(DatApp3,O_EW_REPLACE_CLIP)))
        hInfoPrint(NOSTR_NO_TEXT_COPIED);
    else
        hInfoPrint(NOSTR_TEXT_COPIED);
    }

METHOD VOID nocomman_ncoe_bring(PR_NOCOMMAN *self)
    {
    INT lkpid;
    ULONG lkfmt;

    CheckEditing(self);
    lkpid=p_send3(w_am->appman.system,O_SY_LINK_PASTE,&lkfmt);
    if (!lkpid || !(lkfmt & (1<<DF_LINK_TEXT)))
        {
        hInfoPrint(-SYS_NOTHING_TO_BRING);
        return;
        }
    p_send4(DatApp3,O_EW_BRING_IN,lkpid,1<<DF_LINK_TEXT);
    }

METHOD VOID nocomman_ncoe_evaluate(PR_NOCOMMAN *self)
    {
    CheckEditing(self);
    p_send2(DatApp3,O_EW_EVALUATE);
    }

METHOD VOID nocomman_ncow_title(PR_NOCOMMAN *self,INT commid)
    {
    commid-=O_NCOW_TITLE;
    FocusToWithCheck(self,commid);
    }

METHOD VOID nocomman_ncox_psetup(VOID)
    {
    p_send2(w_ws,O_WS_EDIT_PRINT_CONTEXT);
    }

METHOD VOID nocomman_nco_switch_focus(PR_NOCOMMAN *self,INT mods)
    {
    INT which;

    which=self->nocomman.which;
    if (mods&W_SHIFT_MODIFIER)
        {
        if (!which--)
            which=FIND_WINDOW;
        }
    else if (which++==FIND_WINDOW)
        which=TITLE_WINDOW;
    FocusTo(self,which);
    }

METHOD VOID nocomman_ncot_set(PR_NOCOMMAN *self,INT commid)
    {
    if (commid>=O_NCOT_SET_ALL)
        eTagAllNotes(commid-O_NCOT_SET_ALL);
    else
        TagCurrentNote(commid-O_NCOT_SET);
    LoadTagStatus(self);
    GiveTagCount();
    }

METHOD VOID nocomman_ncox_goto(PR_NOCOMMAN *self)
    {
    UWORD where;

    where=self->nocomman.where;
    if (!RunDialog(C_NODL_GOTO,NODL_GOTO,&where))
        return;
    if (where==self->nocomman.where)
        return;
    RecordAnyChanges(self);
    SetTo(self,where);
    }

METHOD VOID nocomman_ncox_moveto(PR_NOCOMMAN *self)
    {
    UWORD where;

    where=0;
    if (!RunDialog(C_NODL_GOTO,NODL_MOVETO,&where))
        return;
    if (where==self->nocomman.where)
        return;
    RecordAnyChanges(self);
    eMoveNoteTo(where,self->nocomman.where);
    SetTo(self,where);
    }

METHOD VOID nocomman_ncos_options(PR_NOCOMMAN *self)
    {
    RunDialog(C_NODL_OPTIONS,NODL_OPTIONS,NULL);
    }

METHOD VOID nocomman_nco_quick_find(PR_NOCOMMAN *self,INT dir)
    {
    INT here;

    here=EdwinChanged(self,FIND_WINDOW)?
                                DatApp1->varoot.nrec: self->nocomman.where;
    DoSearch(self,here,dir);
    }

METHOD VOID nocomman_ncos_forwards(PR_NOCOMMAN *self)
    {
    DoSearch(self,self->nocomman.where,+1);
    }

METHOD VOID nocomman_ncos_backwards(PR_NOCOMMAN *self)
    {
    DoSearch(self,self->nocomman.where,-1);
    }

METHOD VOID nocomman_ncos_first(PR_NOCOMMAN *self)
    {
    DoSearch(self,DatApp1->varoot.nrec,+1);
    }

METHOD VOID nocomman_ncos_last(PR_NOCOMMAN *self)
    {
    DoSearch(self,DatApp1->varoot.nrec,-1);
    }

